package com.rpframework.module.common.bottom.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rpframework.core.json.*;
import com.rpframework.core.mybatis.exception.NotPrimaryKeyException;
import com.rpframework.core.mybatis.mapper.Paging;
import com.rpframework.module.common.bottom.entity.Base;
import com.rpframework.module.common.bottom.entity.po.FuzzyBase;
import com.rpframework.module.common.bottom.service.BaseService;
import com.rpframework.module.common.mybatis.mapper.Mapper;
import com.rpframework.utils.ArrayUtils;
import com.rpframework.utils.DateUtils;
import com.rpframework.utils.EntityUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.persistence.Id;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.rpframework.core.json.JsonResp.ok;
import static com.rpframework.module.common.bottom.entity.po.FuzzyBase.gmtName;
import static com.rpframework.module.common.bottom.entity.po.FuzzyBase.uptName;
import static com.rpframework.utils.ClassUtils.getSuperClassGenericType;

/**
 * 基础服务 引用DAO
 *
 * @param <T> 实体类
 * @author 刘兴
 */
public abstract class BaseServiceImpl<T extends Base> extends BaseMapperImpl<T> implements BaseService<T> {

    protected Mapper<T> mapper = null;
    private Class<T> persistentClass;

    @SuppressWarnings("unchecked")
    public BaseServiceImpl(Mapper<T> mapper) {
        this.mapper = mapper;
        super.mapper = this.mapper;
        //getClass() 返回表示此 Class 所表示的实体（类、接口、基本类型或 void）的超类的 Class。
        this.persistentClass = (Class<T>) getSuperClassGenericType(getClass(), 0);
    }

    @Override
    public JsonResp<T> selectOneJson(T t, String emptyMsg) {
        T one = selectOne(t);
        if (one == null) {
            if (StringUtils.isBlank(emptyMsg)) emptyMsg = "数据没有找到";
            throw new EmptyException(emptyMsg);
        }
        return JsonResp.ok(one);
    }

    @Override
    public JsonResp<?> deleteByIdJson(Object id) {
        return deleteIdsJson(new Object[]{id});
    }

    @Override
    public JsonResp<T> selectOneJson(T t) {
        return selectOneJson(t, null);
    }

    @Override
    public JsonResp<Integer> updateByPrimaryKeySelectiveJson(T t) {
        Integer i = updateByPrimaryKeySelective(t);
        if (i <= 0) {
            return ok("更新成功", 0);
        }
        return JsonResp.ok("更新成功", i);
    }

    @Override
    public T toDayBetweenSet(T t) {
        if (t == null) {
            try {
                t = persistentClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        Date date = new Date();
        Date retainDate = DateUtils.retainDate(date);
        t.setGmtDatetime(retainDate);
        Date dateSetLastSecond = DateUtils.dateSetLastSecond(date);
        t.setUptDatetime(dateSetLastSecond);
        return t;
    }

    @SuppressWarnings("unchecked")
    @Override
    public T selectByField(T record, String field) {
        Class<T> c;
        try {
            c = (Class<T>) Class.forName(record.getClass().getName());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return selectByField(record, field, c);
    }

    @Override
    public int selectCount(T t, Example example) {
        example = merge(t, example);
        return selectCountByExample(example);
    }

    @Override
    public Example.Criteria getExampleCriteria(Example example) {
        example = init(example);
        List<Example.Criteria> criteriaList = example.getOredCriteria();
        if (criteriaList.isEmpty()) {
            return example.createCriteria();
        }
        return criteriaList.get(0);
    }

    @Override
    public Example.Criteria getExampleCriteria() {
        return getExampleCriteria(null);
    }

    /**
     * 条件对象初始化
     *
     * @param example 条件
     * @return 不存在NEW
     */
    @Override
    public Example init(Example example) {
        if (example == null) example = getExample();
        return example;
    }

    @Override
    public JsonResp<List<T>> fuzzySearchJson(T t, T fuzzy) {
        return JsonResp.list(fuzzySearch(t, fuzzy));
    }

    @Override
    public int delete(Example e, T t) {
        return deleteByExample(merge(t, e));
    }

    @Override
    public JsonResp deleteJson(Example e, T t) {
        delete(e, t);
        return new JsonResp().succ("删除成功");
    }

    @Override
    public JsonResp insertJson(T t) {
        if (!insertOne(t)) {
            throw new FailException("添加失败");
        }
        return new JsonResp().succ();
    }

    @Override
    public int updateSelective(T t) {
        return updateByExampleSelective(t, getExample());
    }

    @Override
    public PageInfo<T> fuzzySearch(T t, Example example, T fuzzy, Paging p) {
        startPage(p);
        return new PageInfo<>(fuzzySearch(t, example, fuzzy));
    }


    @Override
    public GmtDateMarry getGmtDateMarry(Date date) {
        String nowDateSimple = DateUtils.dateSimple(date);
        Example example = getExample();
        example.createCriteria().andLike("gmtDatetime", nowDateSimple + "%");
        return new GmtDateMarry(nowDateSimple, example);
    }


    @Override
    public int update(T t) {
        return updateByExample(t, getExample());
    }

    @Override
    public T selectPrimaryKeyInspect(Object key) {
        if (key == null) {
            throw new ParameterException("主键参数不能为空");
        }
        T t = selectByPrimaryKey(key);
        if (t == null) {
            throw new ParameterException("主键在库中不存在");
        }
        return t;
    }

    @Override
    public T selectFirst(T t) {
        List<T> ts = selectByRowBounds(t, new RowBounds(0, 1));
        if (ts.isEmpty()) {
            return null;
        }
        return ts.get(0);
    }

    @Override
    public T selectFirst(Example example) {
        List<T> ts = selectByExampleAndRowBounds(example, new RowBounds(0, 1));
        if (ts.isEmpty()) {
            return null;
        }
        return ts.get(0);
    }

    @Override
    public int insert(T record) {
        insertInit(record);
        return mapper.insert(record);
    }

    @Override
    public int insertSelective(T record) {
        insertInit(record);
        return mapper.insertSelective(record);
    }

    @Override
    public int updateByPrimaryKey(T record) {
        updateInit(record);
        return mapper.updateByPrimaryKey(record);
    }

    @Override
    public int updateByPrimaryKeySelective(T record) {
        updateInit(record);
        return mapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByExample(T record, Object example) {
        updateInit(record);
        return mapper.updateByExample(record, example);
    }

    @Override
    public int updateByExampleSelective(T record, Object example) {
        updateInit(record);
        return mapper.updateByExampleSelective(record, example);
    }

    /**
     * 插入记录初始化
     *
     * @param entity 实体类
     */
    private void insertInit(T entity) {
        entity.setGmtDatetime(new Date());
        entity.setUptDatetime(new Date());
    }

    @Override
    public int insertList(List<T> recordList) {
        recordList.forEach(this::insertInit);
        return mapper.insertList(recordList);
    }

    @Override
    public JsonResp<Integer> insertListJson(List<T> t) {
        return JsonResp.ok(insertList(t));
    }

    /**
     * 更新记录初始化
     *
     * @param entity 实体类
     */
    private void updateInit(T entity) {
        if (entity.getGmtDatetime() == null) {
            entity.setGmtDatetime(new Date());
        }
        entity.setUptDatetime(new Date());
    }


    @Override
    public int deleteByPrimaryKey(Object key) {
        return mapper.deleteByPrimaryKey(key);
    }

    @Override
    public List<T> selectAll() {
        return mapper.selectAll();
    }

    @Override
    public T selectByPrimaryKey(Object key) {
        return mapper.selectByPrimaryKey(key);
    }

    @Override
    public int selectCount(T record) {
        return mapper.selectCount(record);
    }

    @Override
    public List<T> select(T record) {
        return mapper.select(record);
    }

    @Override
    public T selectOne(T record) {
        return mapper.selectOne(record);
    }


    @Override
    public int deleteByExample(Object example) {
        return mapper.deleteByExample(example);
    }

    @Override
    public List<T> selectByExample(Object example) {
        return mapper.selectByExample(example);
    }

    @Override
    public int selectCountByExample(Object example) {
        return mapper.selectCountByExample(example);
    }


    @Override
    public List<T> selectByExampleAndRowBounds(Object example, RowBounds rowBounds) {
        return mapper.selectByExampleAndRowBounds(example, rowBounds);
    }

    @Override
    public List<T> selectByRowBounds(T record, RowBounds rowBounds) {
        return mapper.selectByRowBounds(record, rowBounds);
    }

    @Override
    public int insertUseGeneratedKeys(T record) {
        return mapper.insertUseGeneratedKeys(record);
    }

    @Override
    public boolean updateExample(T record, Object example) {
        return updateByExampleSelective(record, example) > 0;
    }

    @Override
    public boolean updateExampleNullValue(T record, Object example) {
        return updateByExample(record, example) > 0;
    }

    @Override
    public boolean insertOne(T record) {
        return insert(record) > 0;
    }

    @Override
    public T select(T t, Object example) {
        List<T> selectByExampleAndRowBounds = selectByExampleAndRowBounds(example, new RowBounds(0, 1));
        if (selectByExampleAndRowBounds.size() > 0) {
            return selectByExampleAndRowBounds.get(0);
        }
        return null;
    }

    @Override
    public PageInfo<T> selectPage(T t, Paging paging) {
        startPage(paging);
        return new PageInfo<>(select(t));
    }

    @Override
    public PageInfo<T> selectPage(Paging paging) {
        startPage(paging);
        return new PageInfo<>(selectAll());
    }

    /**
     * 判断基础
     * 字段是否有@Id注解
     */
    @Override
    public boolean addOrUpdate(T t) {
        Class<?> clazz = t.getClass();
        boolean isUpdate;
        try {
            isUpdate = isUpdate(t, clazz);
        } catch (NotPrimaryKeyException e) {
            try {
                isUpdate = isUpdate(t, clazz.getSuperclass());
            } catch (NotPrimaryKeyException e1) {
                log.debug("没有主键的实体类", e1);
                isUpdate = false;
            }
        }
        if (isUpdate) {
            log.debug("更新对象");
            updateByPrimaryKeySelective(t);
        } else {
            insertOne(t);
        }
        return isUpdate;
    }


    @Override
    public PageInfo<T> fuzzySearch(T t, Paging paging) {
        startPage(paging);
        return new PageInfo<>(fuzzySearch(t));
    }

    @Override
    public JsonResp<PageInfo<T>> fuzzySearchJson(T t, Paging paging) {
        return JsonResp.pageInfo(fuzzySearch(t, paging));
    }

    /**
     * 是否更新对象
     *
     * @param t     对象
     * @param clazz 字节码
     * @return 是返回true
     */
    private boolean isUpdate(T t, Class<?> clazz) throws NotPrimaryKeyException {
        boolean isUpdate = true;
        boolean hasId = false;
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field :
                declaredFields) {
            if (field.getAnnotation(Id.class) != null) {
                hasId = true;
                try {
                    String name = field.getName();
                    name = name.substring(0, 1).toLowerCase() + name.substring(1);
                    Method method = clazz.getMethod("get" + name.substring(0, 1).toUpperCase() + name.substring(1));
                    try {
                        Object invoke = method.invoke(t);
                        if (invoke == null) {
                            isUpdate = false;
                            break;
                        }
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        throw new FailException(e);
                    }
                } catch (NoSuchMethodException e) {
                    throw new FailException(e);
                }
            }
        }
        if (!hasId) {
            throw new NotPrimaryKeyException("没有找到主键");
        }
        return isUpdate;
    }

    @Override
    public PageInfo<T> selectPageEmpty(Paging paging, String message) {
        PageInfo<T> selectPage = selectPage(paging);
        if (selectPage.getList() == null || selectPage.getList().size() <= 0) {
            JsonExceptionHandling.empty(message);
        }
        return selectPage;
    }

    @Override
    public PageInfo<T> selectPageEmpty(Paging paging) {
        return selectPageEmpty(paging, null);
    }

    @Override
    public PageInfo<T> selectPageEmpty(T t, Paging paging, String message) {
        PageInfo<T> selectPage = selectPage(t, paging);
        if (selectPage.getList() == null || selectPage.getList().size() <= 0) {
            JsonExceptionHandling.empty(message);
        }
        return selectPage;
    }

    @Override
    public PageInfo<T> selectPageEmpty(T t, Paging paging) {
        return selectPageEmpty(t, paging, null);
    }

    @Override
    public boolean deleteIds(List<Object> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new ParameterException("删除主键不能为空");
        }
        Example example = getExample();
        example.createCriteria().andIn("id", ids);
        return deleteByExample(example) == ids.size();
    }

    @Override
    public boolean deleteIds(Object[] ids) {
        return deleteIds(Arrays.asList(ids));
    }

    @Override
    public void deleteIdsAll(Object[] ids) {
        deleteIdsAll(Arrays.asList(ids));
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void deleteIdsAll(List<Object> ids) {
        if (!deleteIds(ids)) {
            throw new RuntimeException("批量删除未完全删除");
        }
    }

    @Override
    public JsonResp selectById(Object id, String message) {
        T key = selectByPrimaryKey(id);
        if (key == null) {
            JsonExceptionHandling.parameter(message);
        }
        return ok(message, key);
    }

    @Override
    public JsonResp selectById(Object id) {
        return selectById(id, "主键不存在");
    }

    @Override
    public JsonResp<List<T>> selectJson(String message) {
        List<T> selectAll = selectAll();
        JsonResp<List<T>> json = new JsonResp<>();
        if (selectAll.isEmpty()) {
            json.empty(message);
        } else {
            json.succ(selectAll);
        }
        return json;
    }

    @Override
    public JsonResp selectJson() {
        return selectJson(null);
    }


    @Override
    public List<T> fuzzySearch(T t, boolean isEmpty, String... excludeFields) {
        Map<String, Object> map = EntityUtils.getEntityAttrMap(t, isEmpty, false, excludeFields);
        Example example = getExample();
        Example.Criteria createCriteria = example.createCriteria();
        for (Map.Entry<String, Object> attr : map.entrySet()) {
            Object value = attr.getValue();
            if (value != null) {
                createCriteria.andLike(attr.getKey(), "%" + value.toString() + "%");
            }
        }
        return selectByExample(example);
    }

    @Override
    public List<T> fuzzySearch(T t, Example example) {
        return fuzzySearchEmpty(t, example);
    }

    @Override
    public List<T> fuzzySearchExcludePrimaryKey(T t) {
        return fuzzySearchEmpty(t, "id");
    }

    @Override
    public List<T> fuzzySearchEmpty(T t, String... excludeFields) {
        return fuzzySearch(t, true, excludeFields);
    }

    @Override
    public PageInfo<T> fuzzySearch(T t, boolean isEmpty, Paging paging, String... excludeFields) {
        PageHelper.startPage(paging.getPageNum(), paging.getPageSize());
        return new PageInfo<>(fuzzySearch(t, isEmpty, excludeFields));
    }

    @Override
    public PageInfo<T> fuzzySearchEmpty(T t, Paging paging, String... excludeFields) {
        PageHelper.startPage(paging.getPageNum(), paging.getPageSize());
        return new PageInfo<>(fuzzySearchEmpty(t, excludeFields));
    }

    @Override
    public PageInfo<T> fuzzySearchExcludePrimaryKey(T t, Paging paging) {
        startPage(paging);
        return new PageInfo<>(fuzzySearchExcludePrimaryKey(t));
    }

    @Override
    public JsonResp<List<T>> selectAllJson() {
        return JsonResp.list(selectAll());
    }

    @Override
    public int updates(List<T> ts) {
        int length = 0;
        for (T t : ts) {
            updateByPrimaryKeySelective(t);
            length++;
        }
        return length;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public boolean updatesAll(List<T> ts) {
        int updates = updates(ts);
        if (updates != ts.size()) {
            throw new RuntimeException("更新失败");
        }
        return true;
    }

    @Override
    public JsonResp updatesJson(List<T> ts) {
        try {
            JsonResp json = new JsonResp();
            boolean updatesAll = updatesAll(ts);
            if (updatesAll) {
                return json.succ("更新成功");
            } else {
                return json.failRes("更新成功,没完整更新");
            }
        } catch (Exception e) {
            JsonExceptionHandling.fail("更新失败");
        }
        return null;
    }

    @Override
    public List<T> fuzzySearch(T t, boolean isEmpty, Example example, String... excludeFields) {
        Map<String, Object> map = EntityUtils.getEntityAttrMap(t, isEmpty, false, excludeFields);
        List<Example.Criteria> criteria = example.getOredCriteria();
        Example.Criteria createCriteria = null;
        if (criteria != null && criteria.size() > 0) {
            createCriteria = criteria.get(0);
        }
        if (createCriteria == null) {
            createCriteria = example.createCriteria();
        }
        for (Map.Entry<String, Object> attr : map.entrySet()) {
            Object value = attr.getValue();
            if (value != null) {
                createCriteria.andLike(attr.getKey(), "%" + value.toString() + "%");
            }
        }
        return selectByExample(example);
    }


    @Override
    public List<T> fuzzySearchEmpty(T t, Example example, String... excludeFields) {
        return fuzzySearch(t, true, example, excludeFields);
    }

    @Override
    public List<T> fuzzySearchExcludePrimaryKey(T t, Example example) {
        return fuzzySearch(t, true, example, "id");
    }

    @Override
    public PageInfo<T> fuzzySearch(T t, boolean isEmpty, Paging paging, Example example, String... excludeFields) {
        PageHelper.startPage(paging.getPageNum(), paging.getPageSize());
        return new PageInfo<>(fuzzySearch(t, isEmpty, example, excludeFields));
    }

    @Override
    public PageInfo<T> fuzzySearchEmpty(T t, Paging paging, Example example, String... excludeFields) {
        return fuzzySearch(t, true, paging, example, null, excludeFields);
    }

    @Override
    public PageInfo<T> fuzzySearch(T t, boolean isEmpty, Paging paging, Example example, T fuzzy, String... excludeFields) {
        startPage(paging);
        return new PageInfo<>(fuzzySearch(t, true, example, fuzzy, excludeFields));
    }

    @Override
    public List<T> fuzzySearch(T t, boolean isEmpty, Example example,
                               T fuzzy, String... excludeFields) {
        if (fuzzy != null) {
            example = merge(fuzzy, example);
        }
        return fuzzySearch(t, true, example, excludeFields);
    }

    private Example merge(T t, Example example) {
        Example.Criteria exampleCriteria = getExampleCriteria(example);

        Map<String, Object> entityAttrMap = EntityUtils.getEntityAttrMap(t, true, true);
        for (Map.Entry<String, Object> attr : entityAttrMap.entrySet()) {
            Object value = attr.getValue();
            if (value != null) {
                exampleCriteria.andCondition(attr.getKey() + "=", attr.getValue());
            }
        }
        return example;
    }


    @Override
    public List<T> fuzzySearch(T t, Example example, T fuzzy, String... excludeFields) {
        return fuzzySearch(t, true, example, fuzzy, excludeFields);
    }

    @Override
    public List<T> fuzzySearch(T t, T fuzzy, String... excludeFields) {
        return fuzzySearch(t, getExample(), fuzzy, excludeFields);
    }

    @Override
    public List<T> fuzzySearch(T t, T fuzzy) {
        return fuzzySearch(t, fuzzy, new String[]{});
    }

    @Override
    public PageInfo<T> fuzzySearchExcludePrimaryKey(T t, Paging paging, Example example) {
        return fuzzySearchEmpty(t, paging, example, "id");
    }

    @Override
    public JsonResp<PageInfo<T>> selectPageJson(T t, Paging paging) {
        return new JsonResp<PageInfo<T>>().pageInfoV2(selectPage(t, paging));
    }

    @Override
    public JsonResp<PageInfo<T>> selectPageJson(Example example, Paging paging) {
        return selectPageJson(example, paging, null);
    }

    @Override
    public JsonResp<PageInfo<T>> selectPageJson(Example example, Paging paging, T t) {
        return JsonResp.pageInfo(selectPage(example, t, paging));
    }

    @Override
    public PageInfo<T> selectPage(Example example, T t, Paging paging) {
        startPage(paging);
        return new PageInfo<>(selects(t, example));
    }

    @Override
    public PageInfo<T> selectPage(Example example, Paging paging) {
        startPage(paging);
        return new PageInfo<>(selectByExample(example));
    }

    @Override
    public JsonResp selectPageJSON(Example example, Paging paging) {
        return JsonResp.pageInfo(selectPage(example, paging));
    }

    @Override
    public JsonResp selectPageJson(Paging paging) {
        return JsonResp.pageInfo(selectPage(paging));
    }

    /**
     * 开始分页
     *
     * @param paging 分页数据
     */
    @Override
    public void startPage(Paging paging) {
        paging = Paging.init(paging);
        PageHelper.startPage(paging.getPageNum(), paging.getPageSize());
    }

    @Override
    public Example getExample() {
        return new Example(persistentClass);
    }

    @Override
    public void add(T t) {
        if (!insertOne(t)) {
            throw new FailException("添加纪录失败");
        }
    }

    @Override
    public int update(T data, T e) {
        if (e == null) return update(data);
        Example example = getExample();
        example = merge(e, example);
        return updateByExampleSelective(data, example);
    }

    @Override
    public List<T> selects(T t, Example example) {
        if (t != null) {
            example = merge(t, example);
        }
        return selectByExample(example);
    }

    @Override
    public JsonResp<List<T>> selectsJson(T t, Example example) {
        return JsonResp.list(selects(t, example));
    }

    @Override
    public PageInfo<T> selects(Paging paging, T t, Example example) {
        startPage(paging);
        return new PageInfo<>(selects(t, example));
    }

    @Override
    public JsonResp selectsJson(Paging paging, T t, Example example) {
        return JsonResp.pageInfo(selects(paging, t, example));
    }

    @Override
    public JsonResp<List<T>> selectsJson(T t) {
        return JsonResp.list(select(t));
    }

    @Override
    public JsonResp selectsByIdsJson(Object[] ids) {
        if (ArrayUtils.isEmpty(ids)) {
            throw new ParameterException("查询主键参数不能为空");
        }
        return JsonResp.list(selectsByIds(ids));
    }

    @Override
    public List<T> fuzzySearch(T t, boolean isEmpty) {
        return fuzzySearch(t, isEmpty, new String[]{});
    }

    @Override
    public List<T> fuzzySearch(T t) {
        return fuzzySearch(t, true);
    }

    @Override
    public List<T> selectsByIds(Object[] ids) {
        return selectsByIds(Arrays.asList(ids));
    }

    @Override
    public List<T> selectsByIds(List<?> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new ParameterException("查询主键不能为空");
        }
        Example example = getExample();
        example.createCriteria().andIn("id", ids);
        return selectByExample(example);
    }

    @Override
    public JsonResp deleteJson(T t) {
        int i = delete(t);
        JsonResp json = new JsonResp();
        if (i <= 0) {
            json.empty("没有可删除的数据");
        } else {
            json.setSucc("删除成功");
        }
        return json;
    }

    @Override
    public JsonResp fuzzySearchJson(T t, Example example) {
        return JsonResp.list(fuzzySearch(t, example));
    }

    @Override
    public JsonResp fuzzySearchJson(T t) {
        return JsonResp.list(fuzzySearch(t));
    }

    @Override
    public JsonResp<?> addOrUpdateJson(T t) {
        addOrUpdate(t);
        return new JsonResp<>().succ("操作成功");
    }

    @Override
    public JsonResp<?> deleteIdsJson(Object[] ids) {
        return deleteIdsJson(Arrays.asList(ids));
    }

    @Override
    public JsonResp<?> deleteIdsJson(List<Object> ids) {
        deleteIds(ids);
        return new JsonResp<>().succ("删除成功");
    }

    /**
     * 生产基本字段查询的语句
     */
    private Example baseFieldGenderExample(T t, FuzzyBase fuzzyBase) {
        boolean dateContain = fuzzyBase.isDateContain(), upt = fuzzyBase.isUpt(), greaterThan = fuzzyBase.isGreaterThan();
        Example example = getExample();
        String name = gmtName, than = ">";
        if (!upt) name = uptName;
        if (dateContain) than += "=";
        if (!greaterThan) {
            than = "<";
            if (dateContain) than += "=";
        }
        Date createDatetime = t.getGmtDatetime(), uptDatetime = t.getUptDatetime();
        Example.Criteria criteria = example.createCriteria();

        Class<?>[] declaredClasses = Example.class.getDeclaredClasses();
        Method column = null;
        for (Class<?> c : declaredClasses)
            try {
                column = c.getDeclaredMethod("column", String.class);
            } catch (NoSuchMethodException e) {
                log.debug("ERROR", e);
            }
        String n;
        if (column == null) throw new FailException();
        try {
            column.setAccessible(true);
            n = column.invoke(criteria, name) + than;
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }

        if (createDatetime != null & uptDatetime != null) {
            criteria.andBetween(name, createDatetime, uptDatetime);
        } else if (createDatetime != null) {
            criteria.andCondition(n, createDatetime);
        } else if (uptDatetime != null) {
            criteria.andCondition(n, uptDatetime);
        }
        return example;
    }

    @Override
    public PageInfo<T> fuzzyBaseField(T t, FuzzyBase fuzzyBase, Paging paging) {
        startPage(paging);
        return new PageInfo<>(fuzzyBaseField(t, fuzzyBase));
    }

    @Override
    public List<T> selectBaseField(T t, T n, FuzzyBase fuzzyBase) {
        Example example = baseFieldGenderExample(t, fuzzyBase);
        return selectByExample(merge(n, example));
    }

    @Override
    public PageInfo<T> selectBaseFieldPage(T t, T n, FuzzyBase fuzzyBase, Paging paging) {
        startPage(paging);
        return new PageInfo<>(selectBaseField(t, n, fuzzyBase));
    }

    @Override
    public JsonResp<PageInfo<T>> fuzzyBaseFieldJson(T t, FuzzyBase fuzzyBase, Paging paging) {
        return JsonResp.pageInfo(fuzzyBaseField(t, fuzzyBase, paging));
    }

    @Override
    public JsonResp<List<T>>  fuzzyBaseFieldJson(T t, FuzzyBase fuzzyBase) {
        return JsonResp.list(fuzzyBaseField(t, fuzzyBase));
    }

    @Override
    public PageInfo<T> selectBaseField(T t, FuzzyBase fuzzyBase, Paging paging) {
        Example example = baseFieldGenderExample(t, fuzzyBase);
        return selects(paging, t, example);
    }

    @Override
    public List<T> selectBaseField(T t, FuzzyBase fuzzyBase) {
        Example example = baseFieldGenderExample(t, fuzzyBase);
        return selects(t, example);
    }

    @Override
    public JsonResp<PageInfo<T>> selectBaseFieldJson(T t, FuzzyBase fuzzyBase, Paging paging) {
        return JsonResp.pageInfo(selectBaseField(t, fuzzyBase, paging));
    }

    @Override
    public JsonResp<List<T>> selectBaseFieldJson(T t, FuzzyBase fuzzyBase) {
        return JsonResp.list(selectBaseField(t, fuzzyBase));
    }

    @Override
    public List<T> fuzzyBaseField(T t, FuzzyBase fuzzyBase) {
        Example example = baseFieldGenderExample(t, fuzzyBase);
        return fuzzySearch(t, example);
    }
}
